<script setup>
import service from '@/utils/request.utils';
import { ElMessage } from 'element-plus';
import { computed, onBeforeMount, ref } from 'vue';
import { Download } from '@element-plus/icons-vue'
import { getCookie } from '@/utils/cookie.utils';
import 'highlight.js/styles/monokai.css';
import Markdown from 'vue3-markdown-it';
import { useStore } from 'vuex'

const store = useStore()


const history = ref([
    {
        role: "AI助手",
        message: "请问我有什么可以帮到你的吗？"
    },
    // {
    //     role: "人类",
    //     message: "请问 1 + 1 等于多少？"
    // },
    // {
    //     role: "AI助手",
    //     message: "### 1+1的结果为2\ndasdasdasdasdsa\n```python\nimport os\nprint(os.executable)\n```",
    //     reference: [{
    //         "file_id": 11, "file_name": "快马带货技术文档", "content": '议论文，又叫说理文，是一种剖\
    //     析事理，论述事理，发表意见，提出主张的文体。作者通过摆事实、讲道理、辨是非、举例子等方法，来确定某观点\
    //     正确或错误，树立或否定某种主张。\n\n议论文具有观点明确、论据充分、语言精炼、论证合理、有\
    //     严密的逻辑性的特点。\nsdasd ', "page_number": 11, distance: 0.6566
    //     }, {
    //         "file_id": 11, "file_name": "快马带货技术文档", "content": '议论文，又叫说理文，是一种剖\
    //     析事理，论述事理，发表意见，提出主张的文体。作者通过摆事实、讲道理、辨是非、举例子等方法，来确定某观点\
    //     正确或错误，树立或否定某种主张。\n\n议论文具有观点明确、论据充分、语言精炼、论证合理、有\
    //     严密的逻辑性的特点。', "page_number": 11, distance: 0.6566
    //     }, {
    //         "file_id": 11, "file_name": "快马带货技术文档", "content": '议论文，又叫说理文，是一种剖\
    //     析事理，论述事理，发表意见，提出主张的文体。作者通过摆事实、讲道理、辨是非、举例子等方法，来确定某观点\
    //     正确或错误，树立或否定某种主张。\n\n议论文具有观点明确、论据充分、语言精炼、论证合理、有\
    //     严密的逻辑性的特点。', "page_number": 11, distance: 0.6566
    //     }]
    // },
    // {
    //     role: "人类",
    //     message: "请问 1 + 1 等于多少？"
    // },
    // {
    //     role: "AI助手",
    //     message: "### 1+1的结果为2\n```python\nimport os\nprint(os.executable)\n```",
    //     reference: [{
    //         "file_id": 11, "file_name": "快马带货技术文档", "content": '议论文，又叫说理文，是一种剖\
    //     析事理，论述事理，发表意见，提出主张的文体。作者通过摆事实、讲道理、辨是非、举例子等方法，来确定某观点\
    //     正确或错误，树立或否定某种主张。\n\n议论文具有观点明确、论据充分、语言精炼、论证合理、有\
    //     严密的逻辑性的特点。', "page_number": 11, distance: 0.6566
    //     }, {
    //         "file_id": 11, "file_name": "快马带货技术文档", "content": '议论文，又叫说理文，是一种剖\
    //     析事理，论述事理，发表意见，提出主张的文体。作者通过摆事实、讲道理、辨是非、举例子等方法，来确定某观点\
    //     正确或错误，树立或否定某种主张。\n\n议论文具有观点明确、论据充分、语言精炼、论证合理、有\
    //     严密的逻辑性的特点。', "page_number": 11, distance: 0.6566
    //     }, {
    //         "file_id": 11, "file_name": "快马带货技术文档", "content": '议论文，又叫说理文，是一种剖\
    //     析事理，论述事理，发表意见，提出主张的文体。作者通过摆事实、讲道理、辨是非、举例子等方法，来确定某观点\
    //     正确或错误，树立或否定某种主张。\n\n议论文具有观点明确、论据充分、语言精炼、论证合理、有\
    //     严密的逻辑性的特点。', "page_number": 11, distance: 0.6566
    //     }]
    // },
    // {
    //     role: "人类",
    //     message: "请问 1 + 1 等于多少？"
    // },
    // {
    //     role: "AI助手",
    //     message: "## 1+1的结果为2\n```python\nimport os\nprint(os.executable)\n```",
    //     reference: [{
    //         "file_id": 11, "file_name": "快马带货技术文档", "content": '议论文，又叫说理文，是一种剖\
    //     析事理，论述事理，发表意见，提出主张的文体。作者通过摆事实、讲道理、辨是非、举例子等方法，来确定某观点\
    //     正确或错误，树立或否定某种主张。\n\n议论文具有观点明确、论据充分、语言精炼、论证合理、有\
    //     严密的逻辑性的特点。', "page_number": 11, distance: 0.6566
    //     }, {
    //         "file_id": 11, "file_name": "快马带货技术文档", "content": '议论文，又叫说理文，是一种剖\
    //     析事理，论述事理，发表意见，提出主张的文体。作者通过摆事实、讲道理、辨是非、举例子等方法，来确定某观点\
    //     正确或错误，树立或否定某种主张。\n\n议论文具有观点明确、论据充分、语言精炼、论证合理、有\
    //     严密的逻辑性的特点。', "page_number": 11, distance: 0.6566
    //     }, {
    //         "file_id": 11, "file_name": "快马带货技术文档", "content": '议论文，又叫说理文，是一种剖\
    //     析事理，论述事理，发表意见，提出主张的文体。作者通过摆事实、讲道理、辨是非、举例子等方法，来确定某观点\
    //     正确或错误，树立或否定某种主张。\n\n议论文具有观点明确、论据充分、语言精炼、论证合理、有\
    //     严密的逻辑性的特点。', "page_number": 11, distance: 0.6566
    //     }]
    // }

])
const question = ref(null)
const btn = ref(false)

const hubList = ref([])
const databaseList = ref([])


const hubSelectedOrigin = ref(null)

const hubSelected = computed({
    get() {
        return hubSelectedOrigin.value
    },
    // 需要监听数据变化
    async set(newValue) {
        hubSelectedOrigin.value = newValue
        queryDatabase()
    }
})

const databaseSelectedOrigin = ref(null)
const databaseSelected = computed({
    get() {
        return databaseSelectedOrigin.value
    },
    set(newValue) {
        databaseSelectedOrigin.value = newValue
    }
})

async function queryDatabase() {
    if (hubSelectedOrigin == null) {
        ElMessage.warning("请先选择一个知识库")
        return
    } else {
        let res = await service.post("/database/querys", { hubId: hubSelectedOrigin.value["hub_id"] })
        console.log(res)

        if (res.status != 200) {
            ElMessage({
                message: '操作失败: ' + res.status,
                type: 'error'
            })
        }

        if (res.data.code != '0') {
            console.log(res.data)
            ElMessage({
                message: res.data.msg,
                type: "warning"
            })
        } else {
            let data = res.data.data
            databaseList.value = data
            if (data.length == 0) {
                ElMessage.info("该知识库没有数据库源！")
            }
            return
        }

    }
}

async function send() {

    btn.value = true
    if (databaseSelectedOrigin.value == null) {
        ElMessage.warning("未选择一个数据库源")
        btn.value = false
        return
    }


    if (question.value == null || question.value.lenght == 0) {
        ElMessage.warning("聊天输入不能为空")
        btn.value = false
        return
    }

    const message = question.value
    question.value = null


    try {
        let llm = store.state.model
        let temperature = store.state.temperature
        let data = {
            "databaseId": databaseSelectedOrigin.value.id, "question": message, "llm": llm, "temperature": temperature
        }
        let res = service.post("/chat/sql", data)
        history.value.push({ "role": "人类", "message": message })
        res = await res;
        console.log(res)
        if (res.status != 200) {
            ElMessage({
                message: '操作失败: ' + res.status,
                type: 'error'
            })
        }

        if (res.data.code != '0') {
            console.log(res.data)
            ElMessage({
                message: res.data.msg,
                type: "warning"
            })
        } else {
            let data = res.data.data
            let k = data.indexOf("SQLResult")
            if (k != -1) {
                data = data.slice(0, k)
            }
            if (data.indexOf("```") != 0) {
                data = '```sql\n' + data + "\n```"
            }
            history.value.push({ "role": "AI助手", "message": data })
            btn.value = false
            return
        }

        history.value.pop()
        btn.value = false
        return
    } catch (e) {
        console.log(e)
        ElMessage.error(e)
        history.value.pop()
        btn.value = false
        return
    }
}


function download(file) {
    console.log(file)
    const downloadUrl = import.meta.env.VITE_API_ADDR + "/" + "download/document?hubId=" + file["hub_id"] + "&fileId=" + file["id"] + "&token=" + getCookie("token")
    window.open(downloadUrl, '_blank')
}


onBeforeMount(async () => {
    let res = await service.post("/hub/queryAll")
    console.log(res)

    if (res.status != 200) {
        ElMessage({
            message: '操作失败: ' + res.status,
            type: 'error'
        })
    }

    if (res.data.code != '0') {
        console.log(res.data)
        ElMessage({
            message: RESPONSE_MESSAGE[res.data.code],
            type: "warning"
        })
    } else {
        let data = res.data.data
        for (let i in data) {
            data[i]["hub_group"] = data[i]["hub_name"] + " (群组：" + data[i]["group_name"] + ")"
        }
        hubList.value = data
        return
    }

    history.value.pop()
    btn.value = false
    return
})

</script>

<template>
    <div id="outer">
        <h2 style="position: absolute;top: -15px">Chat SQL</h2>
        <div id="chat-framework">
            <div id="chat-content">
                <div class="chat-message-item" v-for="item in history">
                    <div class="chat-human-message" v-if="item.role == '人类'">
                        <div class="human-content content-padding">
                            {{ item.message }}
                        </div>
                        <div class="user">
                            你
                        </div>
                    </div>
                    <div class="chat-ai-message" v-else>
                        <div class="user">
                            AI
                        </div>
                        <div class="ai-content content-padding">
                            <Markdown class="markdown-style" :source="item.message"></Markdown>
                            <div class="ai-reference" v-if="item.reference">
                                引用：<div class="ai-reference-item" v-for="reference in item.reference">
                                    <el-tooltip effect="dark" popper-class="tooltip-width">
                                        <a>{{ reference.distance }}</a>
                                        <template #content>
                                            <div>
                                                <p style="font-size: smaller; font-weight: 800;white-space: pre-wrap;">
                                                    {{ "《" + reference.file_name + "》》 页码：" + reference.page_number }}
                                                </p>
                                                <p style="white-space: pre-wrap;">
                                                    {{ reference.content }}
                                                </p>
                                            </div>
                                        </template>
                                    </el-tooltip>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div id="chat-input">
                <el-input placeholder="请输入聊天信息" v-model="question" @keyup.enter.native="send"
                    id="chat-input-box"></el-input>
                <el-button id="chat-input-btn" @click="send" :disabled="btn" type="success">发送</el-button>
            </div>
        </div>
        <div id="hub-panel">
            <div id="panel">
                <el-form-item label="请选择知识库">
                    <el-select v-model="hubSelected" placeholder="选择一个知识库" size="large" style="width: 240px">
                        <el-option v-for="hub in hubList" :key="hub.hub_id" :label="hub.hub_group" :value="hub" />
                    </el-select>
                </el-form-item>
            </div>
            <div id="file-list">
                <el-form-item v-if="databaseList.length > 0" label="请选择数据库源">
                    <el-select v-model="databaseSelected" placeholder="选择一个数据库源" size="large" style="width: 240px">
                        <el-option v-for="database in databaseList" :key="database.id" :label="database.database"
                            :value="database" />
                    </el-select>
                </el-form-item>
            </div>
        </div>
    </div>
</template>


<style scoped>
#outer {
    position: relative;
    margin: auto;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-around;
}

#chat-framework {
    width: 60%;
    height: 90%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-around;
}

#chat-content {
    height: 90%;
    width: 100%;
    overflow: auto;
    border: 2px rgb(120, 120, 120) dashed;
    border-radius: 5px;
    background-color: rgb(245, 245, 245);

}

.chat-message-item {
    width: 100%;
    position: relative;
    margin-top: 5px;
    margin-bottom: 5px;
}

.chat-human-message {
    display: flex;
    flex-direction: row;
    justify-content: flex-end;
    width: 100%;
}

.chat-ai-message {
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    width: 100%;
}

.content-padding {
    padding-left: 10px;
    padding-right: 10px;
    padding-top: 7px;
    padding-bottom: 7px;
}

.human-content {
    max-width: 50%;
    background-color: goldenrod;
    border-radius: 5px;
}

.ai-content {
    max-width: 50%;
    background-color: white;
    display: flex;
    flex-direction: column;
    border-radius: 5px;
}

.ai-reference {
    margin-top: 10px;
    padding-top: 5px;
    border-top: 2px rgb(200, 200, 200) solid;
    font-size: 0.1em;
    font-weight: 800;
    display: flex;
    flex-direction: row;
    white-space: normal;
}

.ai-reference-item {
    width: fit-content;
    height: fit-content;
    padding-left: 3em;
    padding-right: 5em;
    cursor: pointer;
}

.user {
    margin-left: 0.3em;
    margin-right: 0.3em;
    margin-top: 5px;
    font-size: 1.2em;
    width: fit-content;
    font-weight: 700;
}


#chat-input {
    height: 10%;
    width: 100%;
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
}

#hub-panel {
    width: 38%;
    height: 90%;
    border: 2px rgb(200, 200, 200) solid;
    border-radius: 1em;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}

#panel {
    height: 35%;
    width: 90%;
    padding-top: 5%;
    padding-left: 5%;
    padding-right: 10%;
}

#file-list {
    height: 65%;
    width: 100%;
    overflow: auto;
    padding-left: 2em;
}
</style>

<style lang="less">
.tooltip-width {
    max-width: 800px;
}

.markdown-style {
    margin-top: -15px;
    margin-bottom: -15px;
}
</style>

